#include "Animation.h"
Animation::Animation(Anims* a, InterpolationMode m)
	:m_totalTime(0),
	m_currentTime(0),
	m_activateKeyFrame(0),
	m_anims(a),
	m_activateAnim(NULL),
	m_preFrameTime(0),
	m_interMode(m),
	m_speed(1.0f)
{
	m_activateAnim=(*m_anims)[0];
	m_totalTime=m_activateAnim->keyFrames->size()*1000/m_activateAnim->frameRate;
	m_preFrameTime=1000/m_activateAnim->frameRate;
}

Animation::~Animation()
{
	delete m_anims;
}

void Animation::SetSpeed(const float speed)
{
	m_speed=speed;
}

bool Animation::CalcAnim(const int incrTime,Bones* bones)
{

	m_currentTime+=m_speed*incrTime;
	if(m_currentTime>m_totalTime)
		m_currentTime%=m_totalTime;


	m_activateKeyFrame=m_currentTime/m_preFrameTime;
	
	float rate=static_cast<float>(m_currentTime)/m_preFrameTime-m_activateKeyFrame;

	int nextFrame=0;
	if(static_cast<size_t>(m_activateKeyFrame)<m_activateAnim->keyFrames->size()-1)
	{
		nextFrame=m_activateKeyFrame+1;
	}
	else
	{
		m_activateKeyFrame=0;
		nextFrame=1;
	}


	if(bones==NULL)
		EXCEPTION("")
	Interpolation(
		(*m_activateAnim->keyFrames)[m_activateKeyFrame],
		(*m_activateAnim->keyFrames)[nextFrame],
		rate,
		bones);
	
	
	return true;
}

void Animation::LinerInterpolation(const Bones* a, const Bones* b,float f, Bones* bones)
{
	if(f>1.0f)
		EXCEPTION("")

	size_t boneSize=a->size();
	
	if(boneSize!=b->size())
		EXCEPTION("")
	
	for(size_t tt=0;tt<boneSize;tt++)
	{
		Bone* tmpBone=new Bone;
		
		XMFLOAT3 verta=(*a)[tt]->pos;
		XMFLOAT3 vertb=(*b)[tt]->pos;
		XMFLOAT4 orienta=(*a)[tt]->orientation;
		XMFLOAT4 orientb=(*b)[tt]->orientation;
		
		tmpBone->pos.x=verta.x+f*(vertb.x-verta.x);
		tmpBone->pos.y=verta.y+f*(vertb.y-verta.y);
		tmpBone->pos.z=verta.z+f*(vertb.z-verta.z);
		XMVECTOR orientaVector=XMVectorSet(orienta.x,orienta.y,orienta.z,orienta.w);
		XMVECTOR orientbVector=XMVectorSet(orientb.x,orientb.y,orientb.z,orientb.w);
		XMStoreFloat4(&tmpBone->orientation,XMQuaternionSlerp(orientaVector,orientbVector,f));
		
		bones->push_back(tmpBone);
	}

}

void Animation::Interpolation(const Bones* a, const Bones* b,float f, Bones* rt)
{
	switch(m_interMode)
	{
	case LINER_INTERPOLATION:
		return LinerInterpolation(a,b,f,rt);
	default:
		EXCEPTION("")
	}
}
